import json
import logging
import time
import asyncio
from typing import Dict, Any, Optional, Callable, List
import base64

class MessageHandler:
    """消息处理器，负责处理各种类型的消息路由和处理"""
    
    def __init__(self, 
                 logger: logging.Logger,
                 send_json_callback: Callable,
                 set_state_callback: Callable,
                 audio_player=None,
                 iot_handler=None,
                 client=None):
        """初始化消息处理器
        
        Args:
            logger: 日志记录器
            send_json_callback: 发送JSON消息的回调函数
            set_state_callback: 设置状态的回调函数
            audio_player: 音频播放器
            iot_handler: IoT处理器
            client: 客户端对象引用
        """
        self.logger = logger
        self.send_json = send_json_callback
        self.set_state = set_state_callback
        self.audio_player = audio_player
        self.iot_handler = iot_handler
        self.client = client  # 保存客户端的引用
        
        # TTS缓存
        self.tts_cache = {}
        self.tts_cache_size = 20  # 最多缓存20条TTS
        self.current_tts_cache_key = None
        
        # 音频处理状态标志
        self.first_audio_received = False
        
        # 消息接收状态标志
        self.tts_start_received = False
        self.tts_stop_received = False
        
        # 服务器音频参数
        self.audio_params = {}
        
        # 时间记录
        self.stt_time = 0
        self.llm_response_time = 0
        self.tts_start_time = 0
        
        # 状态标志
        self._next_round_started = False
        
    async def handle_message(self, message: Dict[str, Any], client_state: str, direct_stop_recording_callback: Callable = None):
        """处理接收到的消息
        
        Args:
            message: 消息内容
            client_state: 客户端当前状态
            direct_stop_recording_callback: 直接停止录音的回调函数
        """
        msg_type = message.get("type")
        if msg_type == "stt":
            await self._handle_stt_message(message, client_state, direct_stop_recording_callback)
        elif msg_type == "tts":
            # 优先处理TTS消息，减少延迟
            tts_start = time.time()
            await self._handle_tts_message(message, client_state)
            tts_end = time.time()
            self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] TTS消息处理耗时: {(tts_end - tts_start)*1000:.2f}ms")
        elif msg_type == "llm":
            # 优先处理LLM消息，减少延迟
            llm_start = time.time()
            await self._handle_llm_message(message)
            llm_end = time.time()
            self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] LLM消息处理耗时: {(llm_end - llm_start)*1000:.2f}ms")
        elif msg_type == "iot" and self.iot_handler:
            # 处理IoT消息
            self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 处理IoT消息")
            await self.iot_handler.handle_message(message)
        elif msg_type == "hello":
            # 处理握手消息
            await self._handle_hello_message(message)
        elif msg_type == "audio":
            # 处理音频类型的JSON消息
            await self._handle_audio_json_message(message)
        else:
            self.logger.warning(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 收到未知类型的消息: {msg_type}")
            self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 未知消息内容: {json.dumps(message, ensure_ascii=False)}")
    
    async def _handle_stt_message(self, message: Dict[str, Any], client_state: str, direct_stop_recording_callback: Callable = None):
        """处理STT消息
        
        Args:
            message: STT消息
            client_state: 客户端当前状态
            direct_stop_recording_callback: 直接停止录音的回调函数
        """
        text = message.get("text", "")
        self.stt_time = time.time()  # 记录STT结果接收时间
        self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 识别结果: {text}")

        # 只使用直接方式停止录音，避免创建多个任务
        if client_state == "recording" and direct_stop_recording_callback:
            # 直接停止录音，更高效
            await direct_stop_recording_callback()
    
    async def _handle_tts_message(self, message: Dict[str, Any], client_state: str):
        """处理TTS消息
        
        Args:
            message: TTS消息
            client_state: 客户端当前状态
        """
        if "type" not in message or message["type"] != "tts":
            return
        
        session_id = message.get("session_id")
        state = message.get("state")
        text = message.get("text", "")
        
        self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 处理TTS消息: state={state}")
        
        # 首先确保音频播放器知道TTS事件
        if hasattr(self, 'audio_player') and self.audio_player:
            # 通知音频播放器关于TTS事件
            self.audio_player.handle_tts_event(state, text)
        
        # 检查TTS开始
        if state == "start" or state == "sentence_start":
            # 更新TTS开始状态（用于延迟重发机制）
            if hasattr(self, 'client') and self.client:
                self.client.tts_started = True
                self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 设置 client.tts_started=True")
            
        if state == "start":
            # 显式重置TTS相关标志，确保新对话能正常开始
            self.tts_start_received = True
            self.tts_stop_received = False
            
            # 确保客户端和音频播放器的标志也被重置
            if hasattr(self, 'client') and self.client:
                self.client.tts_stop_received = False
                self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 重置client.tts_stop_received=False")
            
            if hasattr(self, 'audio_player') and self.audio_player:
                self.audio_player.tts_stop_received = False
                # 确保播放结束标志也被重置
                if hasattr(self.audio_player, '_end_triggered'):
                    self.audio_player._end_triggered = False
                self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 重置audio_player.tts_stop_received=False")
            
            # 重置TTS相关状态
            self.first_audio_received = False
            self.tts_start_time = time.time()
            
            # 记录回复时间
            if hasattr(self, 'llm_response_time'):
                self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 从LLM响应到TTS开始耗时: {(self.tts_start_time - self.llm_response_time)*1000:.2f}ms")
            
            # 预期要播放的文本
            self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 播放文本: {text}")
        
        # 检查TTS结束
        elif state == "stop":
            # 重置TTS开始标志，表示TTS已停止
            if hasattr(self, 'client') and self.client:
                self.client.tts_started = False
                self.client.tts_sentence_end_received = False  # 重置句子结束标志
                self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 设置 client.tts_started=False, client.tts_sentence_end_received=False")
                
            total_time = 0
            if hasattr(self, 'tts_start_time'):
                total_time = time.time() - self.tts_start_time
                
            self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] TTS播放总耗时: {total_time*1000:.2f}ms")
            self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 收到TTS停止事件")
            
            # 标记TTS已经停止
            self.tts_stop_received = True
            self.tts_start_received = False
            
            # 同时设置客户端的停止标志（如果可能）
            if hasattr(self, 'client') and self.client:
                self.client.tts_stop_received = True
                self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 设置client.tts_stop_received=True")
            
            # 清除当前缓存的TTS key
            if hasattr(self, 'current_tts_cache_key'):
                self.current_tts_cache_key = None
            
            # 修改：延迟停止音频播放，确保所有语音都能播放完毕
            # 在新线程中处理，避免阻塞当前消息处理
            async def delayed_stop_audio():
                # 检查是否还有未播放完的缓冲区数据
                buffer_size = 0
                if hasattr(self, 'audio_player') and self.audio_player:
                    # 获取当前音频缓冲区大小
                    if hasattr(self.audio_player, 'buffer_lock') and hasattr(self.audio_player, 'audio_buffer'):
                        with self.audio_player.buffer_lock:
                            buffer_size = len(self.audio_player.audio_buffer)
                    
                # 记录缓冲区状态
                self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] TTS停止事件：缓冲区剩余 {buffer_size} 字节数据")
                
                # 标记是否已经触发了播放结束回调
                play_end_triggered = False
                
                if buffer_size > 0:
                    # 计算大约需要多少时间播放完这些数据
                    # 假设16000 sample rate, 2 bytes per sample, mono
                    samples = buffer_size / 2  # 16位样本，每个2字节
                    duration_sec = samples / 16000  # 16000Hz采样率
                    
                    # 不设置超时时间，让音频播放器完全播放完缓冲区内容
                    self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 检测到缓冲区有 {buffer_size} 字节数据 (约 {duration_sec:.2f}秒)，等待自然播放完成")
                    
                    # 监控播放状态，每隔100ms检查一次，直到播放结束
                    while True:
                        # 检查当前缓冲区大小
                        current_buffer_size = 0
                        if hasattr(self.audio_player, 'buffer_lock') and hasattr(self.audio_player, 'audio_buffer'):
                            with self.audio_player.buffer_lock:
                                current_buffer_size = len(self.audio_player.audio_buffer)
                        
                        # 记录日志，便于调试
                        if current_buffer_size < buffer_size:
                            # 每当缓冲区大小减少一定量时打印日志
                            if buffer_size - current_buffer_size > 10000:  # 缓冲区减少了10KB
                                self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 缓冲区播放中: 剩余 {current_buffer_size} 字节 (已播放 {buffer_size - current_buffer_size} 字节)")
                                buffer_size = current_buffer_size
                        
                        # 检查是否还在播放
                        if not self.audio_player.is_audio_playing():
                            self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 检测到音频播放已停止")
                            # 触发播放结束回调
                            await self._trigger_play_end()
                            play_end_triggered = True
                            break
                            
                        # 如果缓冲区已经很小或为空，也可以认为播放结束了
                        if current_buffer_size == 0 or current_buffer_size < 1024:  # 小于1KB时认为基本播放完毕
                            self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 缓冲区已基本播放完毕 (剩余 {current_buffer_size} 字节)")
                            # 触发播放结束回调
                            await self._trigger_play_end()
                            play_end_triggered = True
                            break
                            
                        # 短暂休眠再次检查
                        await asyncio.sleep(0.1)
                else:
                    # 如果缓冲区已经是空的，简单记录
                    self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 缓冲区为空，无需等待播放完成")
                
                # 等待一小段时间，确保音频播放器有机会处理最后几帧
                await asyncio.sleep(0.1)
                
                # 检查播放状态，如果播放器未能自动结束，则手动触发
                if hasattr(self, 'audio_player') and self.audio_player and not play_end_triggered:
                    is_still_playing = self.audio_player.is_audio_playing()
                    buffer_empty = True
                    
                    # 再次检查缓冲区
                    if hasattr(self.audio_player, 'buffer_lock') and hasattr(self.audio_player, 'audio_buffer'):
                        with self.audio_player.buffer_lock:
                            buffer_empty = len(self.audio_player.audio_buffer) == 0 or len(self.audio_player.audio_buffer) < 1024
                    
                    if is_still_playing and buffer_empty:
                        self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 缓冲区已播放完毕，但播放状态未更新，手动触发播放结束")
                        await self._trigger_play_end()
                    elif is_still_playing and not buffer_empty:
                        self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 音频播放中，且缓冲区仍有数据，允许继续播放")
                    else:
                        self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 音频播放已正常结束")
                        # 确保触发播放结束回调，即使没有显式检测到播放停止
                        await self._trigger_play_end()
            
            # 创建异步任务停止音频播放
            asyncio.create_task(delayed_stop_audio())
        
        # 句子开始
        elif state == "sentence_start":
            # 处理句子开始事件
            # self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 句子开始: \"{text}\"")
            # 确保不会在句子开始时误清缓冲区
            if hasattr(self, 'audio_player') and self.audio_player:
                # 只有当播放器的标志被设置为True时，才将其重置为False
                # 这样可以避免在TTS停止后，新的句子开始事件误重置标志
                if not self.tts_stop_received:
                    self.audio_player.tts_stop_received = False
                    self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 保持TTS非停止状态")
                else:
                    self.logger.warning(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 已收到TTS停止事件，但又接收到句子开始事件，这可能是不一致的状态")
        
        # 句子结束
        elif state == "sentence_end":
            # 处理句子结束事件
            # self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 句子结束: \"{text}\"")
            
            # 设置句子结束标志，用于立即触发音频重发
            # 这是新的交互方式：收到第一条句子结束消息时立即重发，不再等待TTS开始
            if hasattr(self, 'client') and self.client:
                self.client.tts_sentence_end_received = True
                self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 设置 client.tts_sentence_end_received=True，触发音频重发机制")
            
            # 确保不会在句子结束时误清缓冲区
            # 如果这是音频流中的中间句子，不要清空缓冲区或停止播放
            if hasattr(self, 'audio_player') and self.audio_player:
                # 如果不是所有句子的最后一句，仅确保播放状态正确
                buffer_size = 0
                with self.audio_player.buffer_lock:
                    buffer_size = len(self.audio_player.audio_buffer)
                if buffer_size > 0:
                    self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 句子结束后，缓冲区仍有 {buffer_size} 字节数据，继续播放")
                    # 确保播放状态正确
                    if not self.audio_player.is_playing:
                        self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 音频未播放，但缓冲区有数据，启动播放")
                        # 确保播放器处于播放状态
                        self.audio_player.start_playback()
    
    async def _trigger_play_end(self):
        """延迟触发音频播放结束回调"""
        try:
            # 添加防止重复触发的标志
            if hasattr(self, '_trigger_play_end_called') and self._trigger_play_end_called:
                self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 播放结束回调已经被触发，跳过")
                return
                
            self._trigger_play_end_called = True
            
            # 设置一个标记到音频播放器，防止它也触发重复的结束回调
            if hasattr(self, 'audio_player') and self.audio_player:
                # 添加一个新的标记属性
                self.audio_player._end_triggered_by_handler = True
                self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 已在音频播放器设置结束标记")
            
            # 短暂延迟，确保所有数据都已处理
            await asyncio.sleep(0.05)  # 从0.2秒减少到0.05秒
            
            # 记录当前TTS停止状态，用于调试
            self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 触发播放结束前的TTS状态: client_stop={getattr(self.client, 'tts_stop_received', None)}, handler_stop={self.tts_stop_received}")
            
            # 确保TTS停止标志保持为True，不要在这里重置
            if hasattr(self, 'client') and self.client:
                # 如果在这之前已经设置了停止标志，则保持它
                was_stopped = getattr(self.client, 'tts_stop_received', False)
                if was_stopped:
                    self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 保持client.tts_stop_received=True")
                elif self.tts_stop_received:
                    # 如果客户端状态不一致，以处理器的状态为准
                    self.client.tts_stop_received = True
                    self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 重置client.tts_stop_received=True")
            
            # 检查音频播放状态，但不强制停止
            if hasattr(self, 'audio_player') and self.audio_player:
                if self.audio_player.is_audio_playing():
                    remaining_buffer = 0
                    with self.audio_player.buffer_lock:
                        remaining_buffer = len(self.audio_player.audio_buffer)
                    
                    if remaining_buffer > 0:
                        self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 音频仍在播放中，剩余缓冲区 {remaining_buffer} 字节，TTS已停止但允许播放完成")
                    else:
                        self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 音频仍在播放中，TTS已停止但缓冲区为空，停止播放")
                        self.audio_player.stop(force=False)
                        await asyncio.sleep(0.05)
            
            # 显式调用客户端的音频播放结束回调
            if hasattr(self, 'client') and self.client and hasattr(self.client, 'on_audio_play_end'):
                self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 显式触发on_audio_play_end回调")
                
                # 记录回调前的状态
                pre_callback_client_stop = getattr(self.client, 'tts_stop_received', None)
                pre_callback_handler_stop = self.tts_stop_received
                self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 回调前TTS状态: client_stop={pre_callback_client_stop}, handler_stop={pre_callback_handler_stop}")
                
                # 调用回调
                self.client.on_audio_play_end()
                
                # 记录回调后的状态
                post_callback_client_stop = getattr(self.client, 'tts_stop_received', None)
                post_callback_handler_stop = self.tts_stop_received
                self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 回调后TTS状态: client_stop={post_callback_client_stop}, handler_stop={post_callback_handler_stop}")
                
                # 如果回调改变了停止状态，需要重新确认
                if pre_callback_client_stop != post_callback_client_stop or pre_callback_handler_stop != post_callback_handler_stop:
                    self.logger.warning(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 警告: 回调改变了TTS停止状态！")
                    
                    # 如果之前确实收到了停止信号，确保状态一致
                    if pre_callback_client_stop or pre_callback_handler_stop:
                        self.tts_stop_received = True
                        if hasattr(self, 'client') and self.client:
                            self.client.tts_stop_received = True
                        self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 已恢复TTS停止状态为True")
            
            # 设置延迟任务重置标志，为下一次触发做准备
            async def reset_trigger_flag():
                await asyncio.sleep(3.0)  # 延长等待时间到3秒，确保不会在短时间内重复触发
                self._trigger_play_end_called = False
                if hasattr(self, 'audio_player') and self.audio_player and hasattr(self.audio_player, '_end_triggered_by_handler'):
                    self.audio_player._end_triggered_by_handler = False
                self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 播放结束回调触发标志已重置")
            
            asyncio.create_task(reset_trigger_flag())
            
        except Exception as e:
            self.logger.error(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 触发播放结束回调时出错: {e}")
            self.logger.error("详细错误信息:", exc_info=True)
            # 重置标志，以便下次可以再次尝试
            self._trigger_play_end_called = False
    
    async def _handle_llm_message(self, message: Dict[str, Any]):
        """处理LLM消息
        
        Args:
            message: LLM消息
        """
        try:
            text = message.get("text", "")
            emotion = message.get("emotion", "neutral")

            # 记录LLM响应时间
            self.llm_response_time = time.time()
            self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] LLM响应: {text[:30]}... (情绪: {emotion})")

            # 这是新的LLM消息，此时应该重置TTS消息标志
            self.tts_start_received = False
            
            # 注意：不要在这里重置tts_stop_received标志
            # 只有在确认新的TTS音频开始时，才应该重置此标志
            # self.tts_stop_received = False  # 这行已删除，不再重置

            # 不再主动发送TTS请求，等待服务端自动处理并发送TTS音频
            # 服务端应该会在处理完LLM响应后自动进行TTS转换并发送音频

            # 检查是否有后续的TTS消息，如果没有，则设置状态为idle并开始下一轮对话
            # 这是为了处理某些情况下服务端可能不发送TTS消息的情况
            asyncio.create_task(self._check_tts_follow_up())

        except Exception as e:
            self.logger.error(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 处理LLM消息时出错: {str(e)}")
    
    async def _handle_hello_message(self, message: Dict[str, Any]):
        """处理握手消息
        
        Args:
            message: 握手消息
        """
        self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 处理服务器问候消息")
        # 保存服务器音频参数配置
        if "audio_params" in message:
            self.audio_params = message["audio_params"]
            self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 更新音频参数: {json.dumps(self.audio_params, ensure_ascii=False)}")
    
    async def _check_tts_follow_up(self):
        """检查LLM消息后的TTS消息"""
        try:
            # 增加等待时间到10秒
            for _ in range(50):  # 最多等待10秒
                await asyncio.sleep(0.2)
                # 如果已收到TTS消息，直接返回
                if (hasattr(self, 'tts_start_received') and self.tts_start_received) or \
                        (hasattr(self, 'tts_stop_received') and self.tts_stop_received):
                    return

            # 超过等待时间仍未收到TTS消息
            self.logger.warning(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 等待TTS消息超时（10秒）")

            # 确保音频系统状态正确
            if self.audio_player:
                if self.audio_player.is_audio_playing():
                    self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 等待当前音频播放完成...")
                    while self.audio_player.is_audio_playing():
                        await asyncio.sleep(0.1)

            # 状态转换
            await self.set_state("idle")
            # 记录日志，但不再尝试启动下一轮对话
            self.logger.debug(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] TTS超时，状态已设为idle")

        except Exception as e:
            self.logger.error(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 检查TTS消息时出错: {e}")
            if self.audio_player:
                self.audio_player.stop()
    
    async def handle_audio_message(self, audio_data: bytes, client_state: str, is_playing_audio: bool, direct_stop_recording_callback: Callable = None):
        """处理音频消息"""
        try:
            # 检查是否有有效的音频播放器
            if not hasattr(self, 'audio_player') or self.audio_player is None:
                self.logger.warning("[音频处理失败] 无法处理音频消息：音频播放器未初始化")
                return
                
            # 检查音频播放器是否可用
            if hasattr(self.audio_player, 'stream') and self.audio_player.stream is None:
                self.logger.warning("[音频处理失败] 无法处理音频消息：音频流未成功初始化")
                return
                
            # 记录收到的音频数据大小
            self.logger.debug(f"收到音频数据，大小: {len(audio_data)} 字节")
            
            # 检查是否为空数据
            if not audio_data or len(audio_data) == 0:
                self.logger.warning("[音频处理失败] 收到空的音频数据")
                return
                
            # 确保TTS状态正确
            # 如果当前是TTS停止状态，但我们收到了新的音频数据，这表明可能是新的TTS开始
            # 我们应该重置TTS停止标志，允许音频播放
            if getattr(self, 'tts_stop_received', False) or \
               (hasattr(self.audio_player, 'tts_stop_received') and self.audio_player.tts_stop_received):
                # 这种情况通常不应该发生，但如果发生了，应该是新的TTS开始了
                # 在某些情况下，可能会先收到音频数据，后收到TTS开始消息
                self.logger.warning(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 检测到TTS曾停止但收到新音频，重置TTS状态")
                self.tts_stop_received = False
                if hasattr(self.audio_player, 'tts_stop_received'):
                    self.audio_player.tts_stop_received = False
                if hasattr(self, 'client') and self.client and hasattr(self.client, 'tts_stop_received'):
                    self.client.tts_stop_received = False
            
            # 尝试添加音频数据到播放器，添加错误重试机制
            max_retries = 2
            for attempt in range(max_retries):
                try:
                    # 服务端发送的二进制音频是Opus格式
                    self.logger.debug(f"添加Opus音频数据到播放器，数据大小: {len(audio_data)} 字节")
                    
                    # 添加到播放器的音频缓冲区，使用默认的is_opus=True
                    self.audio_player.add_audio_data(audio_data)
                    break  # 成功添加后退出重试循环
                except Exception as e:
                    self.logger.error(f"添加音频数据到播放器失败 (尝试 {attempt+1}/{max_retries}): {e}")
                    if attempt == max_retries - 1:
                        # 最后一次尝试失败，记录详细错误并返回
                        import traceback
                        self.logger.error(f"详细错误: {traceback.format_exc()}")
                        self.logger.error(f"无法添加音频数据，可能的Opus解码问题或播放器故障")
                        return
                    else:
                        # 重试前短暂等待
                        await asyncio.sleep(0.01)
            
            # 记录第一次收到音频数据的时间
            if not self.first_audio_received:
                self.first_audio_received = True
                if hasattr(self, 'llm_response_time'):
                    self.logger.info(f"[{time.strftime('%H:%M:%S')}.{int(time.time()*1000)%1000:03d}] 收到第一个音频数据，距LLM响应: {(time.time() - self.llm_response_time)*1000:.2f}ms")
        
        except Exception as e:
            self.logger.error(f"处理音频消息出错: {str(e)}")
            import traceback
            self.logger.error(f"详细错误: {traceback.format_exc()}")
    
    async def _handle_audio_json_message(self, message: Dict[str, Any]):
        """处理音频类型的JSON消息
        
        Args:
            message: 音频消息
        """
        try:
            if message.get("status") == "start":
                self.logger.info("收到音频开始消息")
                if self.audio_player:
                    self.audio_player.play_audio_stream()
            elif message.get("status") == "data":
                audio_data = base64.b64decode(message.get("data", ""))
                if self.audio_player:
                    self.audio_player.add_audio_data(audio_data)
            elif message.get("status") == "end":
                self.logger.info("收到音频结束消息")
                if self.audio_player:
                    self.audio_player.stop_audio_stream()
        except Exception as e:
            self.logger.error(f"处理音频消息出错: {e}")
            import traceback
            traceback.print_exc() 